#!/usr/bin/python
# -*- coding: UTF-8 -*-
from __future__ import absolute_import
from __future__ import unicode_literals
import cv2
import numpy as np


def linear_enhance(image_input, alpha_=1, beta_=0):
    """
    线性变换:
    说明：通过函数y=ax+b对灰度值进行处理，例如对于过暗的图片，其灰度分布在[0,100], 选择a=2,b=10能将灰度范围拉伸到[10, 210]，
         对于计算后大于255的像素值会截断为255
    参数：
    alpha:y=ax+b中的a值
    beta:y=ax+b中的b值
    """
    return cv2.convertScaleAbs(image_input, alpha=alpha_, beta=beta_)


def hist_norm_enhance(image_input, alpha_=350, beta_=10):
    """
    直方图正规化:
    说明：对于上述线性变换，系数alpha，beta需要自己摸索设置。直方图正规化的系数固定，一般将原图片的像素值范围映射到[0,255]范围内。
        假设原图片的像素值分布范围为Input：[min, max], 映射后的范围为Output：[0,255], 则对应的系数a=（255-0）/(max-min),
        系数b=0。
    参数：
    alpha:正规化的值，如果是范围值，为范围的下限
    beta:如果是范围值，为范围的上限；正规化中不用到
    norm_type:normalize的类型
                    cv2.NORM_L1:将像素矩阵的1-范数做为最大值（矩阵中值的绝对值的和）
                    cv2.NORM_L2：将像素矩阵的2-范数做为最大值（矩阵中值的平方和的开方）
                    cv2.NORM_MINMAX：将像素矩阵的∞-范数做为最大值 （矩阵中值的绝对值的最大值）
    """
    # norm_type_dict = {'NORM_L1': cv2.NORM_L1,
    #                   'NORM_L2': cv2.NORM_L2,
    #                   'NORM_MINMAX': cv2.NORM_MINMAX
    #                  }
    return cv2.normalize(image_input, dst=None, alpha=alpha_, beta=beta_, norm_type=cv2.NORM_MINMAX)


def gamma_enhance(image_input, gamma_=0.4):
    """
    伽马变换:
    说明：将输入图像的像素值除以255，归一化到[0,1]区间，然后计算其γ次方值，用公式表示如下，
         其中I(r,c)为归一化后的像素值，当γ=1时原像素值不影响，
         当0<γ<1时，增大像素值，提高图片对比度；
         反之γ>1时能降低图片对比度。
    """
    img_norm = image_input / 255.0  # 注意255.0得采用浮点数
    img_gamma = np.power(img_norm, gamma_) * 255.0
    return img_gamma.astype(np.uint8)


def hist_equa_enhance(image_input):
    """
    全局直方图均衡化:
    说明：直方图均衡化的目的是将原图片每个像素值的像素点个数进行重新分配到[0,255]的256个像素值上，
         使得每个像素值对应的像素点个数近似相等，即重新分配后，0-255的每个像素值对应的像素点个数近似为(rows*cols/256)
    """
    if image_input.ndim == 3:
        temp_image = cv2.cvtColor(image_input, cv2.COLOR_BGR2GRAY)
        return cv2.equalizeHist(temp_image)
    else:
        return cv2.equalizeHist(image_input)


def clahe_enhance(image_input, th_limit_=10, grid_size_=8):
    """
    限制对比度自适应直方图均衡化:
    说明：相比全局直方图均衡化，自适应直方图均衡化将图像划分为不重叠的小块，在每一小块进行直方图均衡化，
         但若小块内有噪声，影响很大，需要通过限制对比度来进行抑制，即限制对比度自适应直方图均衡化。
         如果限制对比度的阈值设置会40，在局部直方图分布中某个像素值出现次数为45，那么多出的5次像素点会被去掉，平均成其他像素值
    参数：
    th_limit_: 限制对比度的阈值，默认为10，直方图中像素值出现次数大于该阈值，多余的次数会被重新分配
    grid_size_: 图像会被划分的size， 如tileGridSize=(8,8),默认为(8,8)
    """
    if image_input.ndim == 3:
        temp_image = cv2.cvtColor(image_input, cv2.COLOR_BGR2GRAY)
        clahe = cv2.createCLAHE(th_limit_, (grid_size_, grid_size_))
        return clahe.apply(temp_image)
    else:
        clahe = cv2.createCLAHE(th_limit_, (grid_size_, grid_size_))
        return clahe.apply(image_input)


if __name__ == "__main__":
    path = r'C:\Users\admin\Desktop\dt\test.bmp'  # place path to your image here
    image_cv = cv2.imread(path, -1)
    gau = hist_norm_enhance(image_cv, 1, 50, 'NORM_MINMAX')
    cv2.imshow("Operation", gau)
    cv2.waitKey(0)

